/********************************************************************************
* @file    app_io_task.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-03-21
* @brief   ADC周期任务
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "os_api.h"
#include "log.h"
#include "kv_sys.h"
#include "atcmd_slave.h"
#include "bsp_adc.h"
/* Private Includes ----------------------------------------------------------*/

#include "ls_gpio.h"
#include "ls_syscfg.h"
#include "app_io.h"
#include "app_main.h"
/* Private Define ------------------------------------------------------------*/

/* Typedef Struct ------------------------------------------------------------*/
/* Public Enum ---------------------------------------------------------------*/
/* External Variables --------------------------------------------------------*/
/* Public Variables ----------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
#if LS_ADC0_EN
OS_TIMER_DECLARE_N(adc0_collection);
uint32_t g_adc0_timer_ms = LS_ADC0_TIMER_CYCLE_MS; // 软定时器扫描周期

extern bsp_adc_cfg_t g_adc0_cfg;
#endif

/* Private Function Prototypes -----------------------------------------------*/
#if LS_ADC0_EN
/**
  * @brief  [ADC采集完毕中断] 发送信号量给主任务
  */
static void adc0_cb(void) {
    bsp_adc0_stop();
    main_send_signal(SIGNAL_ADC0_COLLECTION);
}

static void timer_adc0_collection_cb(void const *arg) {
    // 启动ADC中断转换 将ADC0的通道各采集一遍
    bsp_adc0_start();
}
#endif

#if LS_ADC1_EN
/**
  * @brief  [ADC采集完毕中断] 发送信号量给主任务
  */
static void adc1_cb(void) {
    bsp_adc1_stop();
    main_send_signal(SIGNAL_ADC1_COLLECTION);
}

static void timer_adc1_collection_cb(void const *arg) {
    // 启动ADC中断转换 将ADC1的通道各采集一遍
    bsp_adc1_start();
}
#endif

/* Publib Function Prototypes ------------------------------------------------*/
uint8_t app_adc0_timer_start(void) {
    return os_timer_restart(OS_TIMER_ID(adc0_collection), g_adc0_timer_ms);
}

void app_adc0_timer_stop(void) {
    OS_TIMER_STOP(adc0_collection);
}

uint8_t app_adc0_collection_init(void) {
#if LS_ADC0_EN
    uint32_t timer_ret = 0;
    if (g_adc0_cfg.ch_val) {
        // 注册ADC0采集完毕回调
        bsp_adc0_irq_callback(adc0_cb);
    } else {
        return 2;
    }
    // 创建软定时器 ADC任务
    OS_TIMER_CREATE(adc0_collection, OS_TIMER_PERIODIC);
#endif
    return 0;
}

uint8_t app_adc1_collection_init(void) {
#if LS_ADC1_EN
    uint32_t timer_ret = 0;
    if (g_adc1_cfg.ch_val) {
        // 注册ADC1采集完毕回调
        bsp_adc1_irq_callback(adc1_cb);
    } else {
        return 2;
    }
    // 创建软定时器 ADC任务
    OS_TIMER_CREATE(adc1_collection, OS_TIMER_PERIODIC);
#endif
    return 0;
}

#if ATCMD_EN && LS_ADC0_EN
static int atcmd_get_adc0_info(atcmd_pack_t *pack) {
    char buff[40] = {0};
    uint8_t len = 0;
    len = snprintf(buff, 40, "+ADC0_INFO:%u,%u,%u,%u,%u\r\n",
        g_adc0_cfg.ch_val, 12, g_adc0_cfg.clk_sel,
        g_adc0_cfg.sample_num, g_adc0_timer_ms);
    pack->reply((uint8_t*)buff, len);
    return 0;
}

static int atcmd_set_adc0_cfg(atcmd_pack_t *pack) {
    uint32_t argc[2] = {0};
    char buff[25] = {0};
    uint8_t len = 0;
    pack->argc = sscanf((char*)(pack->data), "%u,%u", &argc[0], &argc[1]);
    if (pack->argc < 2) {
        len = snprintf(buff, 25, "+ADC0_CFG:ARGCERR\r\n");
        pack->reply((uint8_t*)buff, len);
        return -2;
    }
    bsp_adc0_deinit();
    g_adc0_cfg.clk_sel = (uint8_t)argc[0];
    g_adc0_cfg.sample_num = argc[1];
    if (bsp_adc0_init()) {
        len = snprintf(buff, 25, "+ADC0_CFG:ERROR\r\n");
        pack->reply((uint8_t*)buff, len);
    } else {
        len = snprintf(buff, 25, "+ADC0_CFG:OK\r\n");
        pack->reply((uint8_t*)buff, len);
    }
    return 0;
}


static int atcmd_set_adc0_timer_ms(atcmd_pack_t *pack) {
    uint32_t argc[1] = {0};
    char buff[40] = {0};
    uint8_t len = 0;
    pack->argc = sscanf((char*)(pack->data), "%d", &argc[0]);
    if (pack->argc != 1) return -1;
    // 先停止周期任务，并将任务全部取消。
    OS_TIMER_STOP(adc0_collection);
    if (argc[0]) {
        if (os_timer_restart(OS_TIMER_ID(adc0_collection), argc[0]) != OS_OK) {
            len = snprintf(buff, 40, "+ADC0_START:timer restart fail\r\n");
            pack->reply((uint8_t *)buff, len);
        } else {
            len = snprintf(buff, 40, "+ADC0_START:OK\r\n");
            pack->reply((uint8_t *)buff, len);
            g_adc0_timer_ms = argc[0];
        }
    } else {
        if (os_timer_stop(OS_TIMER_ID(adc0_collection)) != OS_OK) {
            len = snprintf(buff, 40, "+ADC0_START:timer stop fail\r\n");
            pack->reply((uint8_t *)buff, len);
        } else {
            len = snprintf(buff, 40, "+ADC0_START:OK\r\n");
            pack->reply((uint8_t *)buff, len);
        }
    }
    return 0;
}

static int atcmd_adc0_start(atcmd_pack_t *pack) {
    char buff[40] = {0};
    uint8_t len = 0;
    if (os_timer_restart(OS_TIMER_ID(adc0_collection), g_adc0_timer_ms) != OS_OK) {
        len = snprintf(buff, 40, "+ADC0_START:timer restart fail\r\n");
        pack->reply((uint8_t *)buff, len);
    } else {
        len = snprintf(buff, 40, "+ADC0_START:OK\r\n");
        pack->reply((uint8_t *)buff, len);
    }
    return 0;
}

static int atcmd_adc0_stop(atcmd_pack_t *pack) {
    char buff[40] = {0};
    uint8_t len = 0;
    if (os_timer_stop(OS_TIMER_ID(adc0_collection)) != OS_OK) {
        len = snprintf(buff, 40, "+ADC0_STOP:timer stop fail\r\n");
        pack->reply((uint8_t *)buff, len);
    } else {
        len = snprintf(buff, 40, "+ADC0_STOP:OK\r\n");
        pack->reply((uint8_t *)buff, len);
    }
    return 0;
}

static int atcmd_get_adc0_val(atcmd_pack_t *pack) {
    char buff[70] = {0};
    uint8_t len = 0;
    len = snprintf(buff, 70, "+ADC0:%u,%u,%u,%u,%u,%u,%u,%u\r\n",
    bsp_adc0_get_ch_val(0), bsp_adc0_get_ch_val(1), bsp_adc0_get_ch_val(2), bsp_adc0_get_ch_val(3),
    bsp_adc0_get_ch_val(4), bsp_adc0_get_ch_val(5), bsp_adc0_get_ch_val(6), bsp_adc0_get_ch_val(7));
    pack->reply((uint8_t *)buff, len);
    return 0;
}

static int atcmd_get_adc0_designated_val(atcmd_pack_t *pack) {
    uint32_t argc[1];
    char buff[30] = {0};
    uint8_t len = 0;
    pack->argc = sscanf((char*)(pack->data), "%d", &argc[0]);
    if (pack->argc != 1) return -1;
    len = snprintf(buff, 30, "+ADC0_CH:%u,%u\r\n", argc[0], bsp_adc0_get_ch_val(argc[0]));
    pack->reply((uint8_t *)buff, len);
    return 0;
}

ATCMD_INIT("AT+ADC0_TIMER_MS=", atcmd_set_adc0_timer_ms);
ATCMD_INIT("AT+ADC0_START", atcmd_adc0_start);
ATCMD_INIT("AT+ADC0_STOP", atcmd_adc0_stop);
ATCMD_INIT("AT+GET_ADC0_VAL=", atcmd_get_adc0_designated_val);
ATCMD_INIT("AT+ADC0?", atcmd_get_adc0_val);

ATCMD_INIT("AT+ADC0_CFG=", atcmd_set_adc0_cfg);
ATCMD_INIT("AT+ADC0_INFO?", atcmd_get_adc0_info);
#endif
